import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { DiscordSnowflake } from "@sapphire/snowflake";
import { plainToInstance } from "class-transformer";
import { ArrayContains, Raw, Repository } from "typeorm";
import { ResultMsg } from "@/common/enum/result-msg.enum";
import Result from "@/common/utils/result.util";
import { SysDept } from "@/database/entity/SysDept";
import { SysDeptType } from "@/database/entity/SysDeptType";
import { CreateDeptTypeDto } from "./dto/create-dept-type.dto";
import { PageDeptTypeDto } from "./dto/page-dept-type.dto";
import { UpdateDeptTypeDto } from "./dto/update-dept-type.dto";
import { DeptTypeDetailVo } from "./vo/dept-type-detail.vo";
import { DeptTypeOptionVo } from "./vo/dept-type-option.vo";
import { DeptTypePageVo } from "./vo/dept-type-page.vo";

@Injectable()
export class DeptTypeService {
    constructor(
        @InjectRepository(SysDeptType) private readonly departTypeRepository: Repository<SysDeptType>,
        @InjectRepository(SysDept) private readonly departRepository: Repository<SysDept>,
    ) {}

    /** 新增部门类型 */
    async create(data: CreateDeptTypeDto) {
        const id = DiscordSnowflake.generate().toString();
        data.cascadeLevel = data.cascadeLevel.sort();
        const newType = this.departTypeRepository.create({ ...data, id });
        await this.departTypeRepository.save(newType);
        return Result.success(id, ResultMsg.CREATE_SUCCESS);
    }

    /** 删除部门类型 */
    async remove(id: string) {
        const hasDepart = await this.departRepository.existsBy({ type: id });
        if (hasDepart) {
            return Result.error(ResultMsg.DELETE_HAS_ASSOCIATION);
        }
        await this.departTypeRepository.update(id, { deletedAt: new Date() });
        return Result.success(id, ResultMsg.DELETE_SUCCESS);
    }

    /** 更新部门类型 */
    async update(type: UpdateDeptTypeDto) {
        if (type.cascadeLevel) {
            type.cascadeLevel = type.cascadeLevel.sort();
        }
        await this.departTypeRepository.update(type.id, { ...type });
        return Result.success(null, ResultMsg.UPDATE_SUCCESS);
    }

    /** 获取详情 */
    async findById(id: string): Promise<Result<DeptTypeDetailVo>> {
        const record = await this.departTypeRepository.findOne({
            select: ["id", "name", "icon", "remark", "cascadeLevel"],
            where: { id },
        });
        const detailVo = plainToInstance(DeptTypeDetailVo, record, { excludeExtraneousValues: true });
        return Result.success(detailVo);
    }

    /** 获取部门类型分页列表 */
    async page(data: PageDeptTypeDto): Promise<Result<DeptTypePageVo[]>> {
        const { name, pageNum, pageSize } = data;
        const queryBuilder = this.departTypeRepository.createQueryBuilder("t");
        queryBuilder.select(["t.id", "t.name", "t.icon", "t.cascadeLevel"]);
        if (name) {
            queryBuilder.where("t.name LIKE :name", { name: `%${name}%` });
        }
        queryBuilder
            .orderBy("t.createdAt", "DESC")
            .skip((pageNum - 1) * pageSize)
            .take(pageSize);
        const [list, total] = await queryBuilder.getManyAndCount();
        const voList = plainToInstance(DeptTypePageVo, list, { excludeExtraneousValues: true });
        return Result.page(voList, { pageNum, pageSize, total });
    }

    /** 获取部门类型选项 */
    async listOptions(level: number): Promise<Result<DeptTypeOptionVo[]>> {
        const items = await this.departTypeRepository.find({
            select: ["id", "name"],
            where: [{ cascadeLevel: ArrayContains([level]) }, { cascadeLevel: Raw((alias) => `${alias} = '{}'`) }],
            order: { createdAt: "DESC" },
        });
        const voList = plainToInstance(DeptTypeOptionVo, items, { excludeExtraneousValues: true });
        return Result.success(voList);
    }
}
